/*
 * ClientHandler.h
 */

#ifndef CLIENTHANDLER_H_
#define CLIENTHANDLER_H_

#include <list>
#include <map>
#include <string>
#include "Mutex.h"
#include "Thread.h"
#include "ClientMessage.h"
#include "../common/LogFile.h"
#include "../common/ServerConfig.h"

class ClientHandler : public Thread {
	private:
		// Mapa y mutex para control de conexiones por cliente
		typedef std::map<std::string, int>::iterator tMsgCountIt;
		std::map<std::string, int> messageCount;
		Mutex messageCount_Mutex;

		// Lista y mutex de mensajes a ser monitoreados
		typedef std::list<ClientMessage*>::iterator tMsgIt;
		std::list<ClientMessage*> messages;
		Mutex messages_Mutex;

		/** Lista y mutex de mensajes nuevos. Se agregan a la lista de
		 * monitoreo tan pronto es posible.
		 */
		std::list<ClientMessage*> newMessages;
		Mutex newMessages_Mutex;

		const ServerConfig& config;
		LogFile& logFile;

		// Contador de mensajes totales en ejecución y su condition variable
		unsigned int currentConn;
		ConditionVariable currentConn_Cv;

		/**
		 * Libera clientes finalizados y mata excedidos en tiempo.
		 */
		void freeProcessedAndKill();

		/**
		 * Registra la entrada del clientId si hay lugar.
		 */
		bool checkInClient(const std::string& clientId);

		/**
		 * Registra la salida del clientId si ingreso previamente.
		 */
		void checkOutClient(const std::string& clientId);

		/**
		 * Une la lista de clientes recién ingresados a la de monitoreo.
		 */
		void mergeClientMessages();

		/**
		 * Mata a todos los clientes.
		 */
		void killEverything();

	public:
		ClientHandler(const ServerConfig& config, LogFile& logFile);
		virtual ~ClientHandler();

		/**
		 * Agrega un nuevo cliente si corresponde y hay lugar o lo descarta.
		 */
		void addNewClient(Socket* sock);

		/**
		 * Se bloquea en caso que no haya espacio para nuevos clientes.
		 */
		void waitForRoom();

		/**
		 * Sobrecarga método de Thread. Desbloquea al objeto y mata clientes.
		 */
		void die();

	protected:
		/**
		 * Monitorea a los clientes existentes y agrega a los recien llegados
		 * a la lista de monitoreo.
		 */
		void run();
};

#endif /* CLIENTHANDLER_H_ */
